using System.ComponentModel.Composition;
using System.Dynamic;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows;
using System.Windows.Interop;
using Caliburn.Micro;
using SS.Common.Logging;
using SS.WPF.Framework.Display.FileDialog;
using SS.WPF.Framework.Display.MsgBox;
using SS.WPF.Framework.Display.MsgBox.ViewModels;
using SS.WPF.Framework.Preference;

namespace SS.WPF.Framework.Display.Dialog
{
    using System;
    using System.Collections.Generic;

    [Export(typeof(IDialogManager))]
    public partial class DialogManager : WindowManager, IDialogManager
    {
        #region Fields
        
        [DllImport("user32.dll")]
        public static extern IntPtr GetActiveWindow();

        [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
        internal static extern int GetWindowText(IntPtr hWnd, [Out] StringBuilder lpString, int nMaxCount);

        /// <summary>
        /// The logger instance
        /// </summary>
        private static readonly ILogger Logger = LoggerManager.GetLogger(typeof(DialogManager).Name);

        public IPreferenceService PreferenceService
        {
            get
            {
                return IoC.Get<IPreferenceService>();
            }
        }

        #endregion

        #region Implementations of IDialogManager

        public bool? ShowDialog<T>() where T : class
        {
            var model = IoC.Get<T>();
            return this.ShowDialog(model);
        }

        public bool? ShowDialog(object input)
        {
            return this.ShowDialog(input, null);   
        }

        public bool? ShowDialog(object rootModel, object context, IDictionary<string, object> settings = null)
        {
            return this.ShowDialog(rootModel, context, Application.Current.MainWindow);
        }

        public bool? ShowDialog(object rootModel, object context, object owner)
        {
            dynamic settings = new ExpandoObject();
            settings.WindowStartupLocation = WindowStartupLocation.CenterScreen;

            var window = CreateWindow(rootModel, true, context, settings);
            var ownerWindow = owner as Window;
            var helper = new WindowInteropHelper(window)
                             {
                                 Owner = ownerWindow != null
                                             ? new WindowInteropHelper(ownerWindow).Handle
                                             : GetActiveWindow()
                             };

            var stringBuilder = new StringBuilder(256);
            GetWindowText(helper.Owner, stringBuilder, stringBuilder.Capacity);

            Logger.DebugFormat("Window current: {0}", stringBuilder.ToString());

            return window.ShowDialog();
        }

        public MsgBoxResult ShowMessageBox(MsgBoxInfo info)
        {
            if (!string.IsNullOrEmpty(info.PreferenceKey)
                && PreferenceService.GetPreferenceStore(typeof(MsgBoxViewModel).Name).GetValue(info.PreferenceKey, false))
            {
                switch (info.Buttons)
                {
                    case MsgBoxButtons.OKCancel:
                    case MsgBoxButtons.OK:
                        return MsgBoxResult.OK;

                    case MsgBoxButtons.YesNoCancel:
                    case MsgBoxButtons.YesNo:
                        return MsgBoxResult.Yes;
                }
            }

            if (info == null)
            {
                throw new ArgumentException("Cannot show message box with null MsgBoxInfo");
            }

            var viewModel = new MsgBoxViewModel(info);
            ShowDialog(viewModel);
            return viewModel.Result;
        }

        public FileDialogResult ShowOpenFileDialog(IEnumerable<FileType> fileTypes, FileType defaultFileType, string defaultFileName, string title)
        {
            return IoC.Get<IFileDialogService>().ShowOpenFileDialog(fileTypes, defaultFileType, defaultFileName, title);
        }

        public FileDialogResult ShowSaveFileDialog(IEnumerable<FileType> fileTypes, FileType defaultFileType, string defaultFileName, string title)
        {
            return IoC.Get<IFileDialogService>().ShowSaveFileDialog(fileTypes, defaultFileType, defaultFileName, title);
        }

        #endregion

        #region Implementations of IWindowManager

        public void ShowWindow(object rootModel, object context = null, IDictionary<string, object> settings = null)
        {
        }

        #endregion     
    }
}